#pragma once
#include <cstdlib>
#include <cassert>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#define DEV "/dev/null"//黑洞文件

/*
一个会话中有且只有一个前台任务 有任意数量的后台任务
要让服务器不受用户登录注销影响 就需要将服务器进程转为守护进程
守护进程自成会话 自建进程组 作为独立会话和后台任务一直存在于服务器中
*/

void daemonSelf(const char* curPath = nullptr)
{
    //1.忽略异常的信号
    signal(SIGPIPE, SIG_IGN);//服务器向客户端返回处理结果时客户端关闭 会发出信号
    //2.不让组长作为守护进程
    if (fork() > 0) exit(0);//调用函数的进程为组长 将组长进程关闭 让其子进程作为守护进程
    pid_t n = setsid();//自成会话
    assert(n != -1);
    //3.守护进程的输入输出脱离终端 需要关闭或重定向以前进程默认打开的文件(0 1 2)
    int fd = open(DEV, O_RDWR);
    if (fd >= 0)//黑洞文件打开成功 将输入输出重定向到该文件
    {
        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);
        close(fd);
    }
    else
    {
        close(0);
        close(1);
        close(2);
    }
    //4.更改进程执行路径(可选操作)
    if (curPath)
        chdir(curPath);
}
